// Copyright 2023 Huawei Cloud Computing Technology Co., Ltd.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

import PROTOCOL_CONFIG from './config/protocolConfig';
import Util from './Util';

const KEYCODE_ENTER_NUMBER_ZONE = 108;
const KEYCODE_ENTER_CTRL_ZONE = 13;

export default class KeyboardInput {
  constructor(containerId, msgHandler, isMobile) {
    this.containerId = containerId;
    this.msgHandler = msgHandler;
    this.isMobile = isMobile;
    this.util = new Util();
    this.inputContainer = null;
    this.touchHandler = null;
    this.cnStart = false;
    this.input = null;
    this.inputId = 'keyboardInput' + Date.now();
  }

  init() {
    const videoContainer = document.getElementById(this.containerId);
    if (!videoContainer) {
      return;
    }

    this.inputContainer = document.createElement('div');
    this.inputContainer.id = 'keyboardInputContent';
    this.input = document.createElement('input');
    this.input.id = this.inputId;
    this.input.type = 'text';

    this.inputContainer.style.cssText = `
            display: block;
            position: absolute;
            bottom: 5px;
            left: 0px;
            height: 0px;
            width: 10px;
            `;
    this.input.style.cssText = `
            height: 0px;
            width: 10px;
            color: white;
            background-color: rgb(37,43,58);
            opacity: 0;
            box-sizing: border-box;
            `;

    if (!this.isMobile) {
      videoContainer.addEventListener(
        'mouseup',
        event => {
          this.onMouseUp(event);
        },
        true,
      );
    }
    this.util.bind(
      this.input,
      'compositionstart',
      this.compositionstart.bind(this),
    );
    this.util.bind(
      this.input,
      'compositionend',
      this.compositionend.bind(this),
    );
    this.util.bind(this.input, 'input', this.onInput.bind(this));
    this.util.bind(this.input, 'keydown', this.onKeydown.bind(this));
    this.inputContainer.appendChild(this.input);
    videoContainer.appendChild(this.inputContainer);
  }

  getTouchHandler(touchHandler) {
    this.touchHandler = touchHandler;
  }

  start() {
    this.inputContainer.style.display = 'block';
    this.input.focus();
  }

  stop() {
    this.input.blur();
    this.inputContainer.style.display = 'none';
  }

  blurInput() {
    this.input.blur();
  }

  onMouseUp(event) {
    this.inputContainer.style.left = event.offsetX + 'px';
    this.inputContainer.style.top = event.offsetY + 'px';
  }

  compositionstart() {
    this.cnStart = true;
  }

  compositionend() {
    this.cnStart = false;
    this.onInput();
  }

  onInput() {
    if (!this.cnStart) {
      this.handleInputMsg(
        this.input.value,
        'KEYBOARD_INPUT',
        PROTOCOL_CONFIG.KEYBOARD_INPUT_MSG_TYPE.IME_PASTE_FROM_PC_SDK,
      );
    }
  }

  onKeydown(event) {
    if (PROTOCOL_CONFIG.PC_INUPT_MAP[event.keyCode]) {
      this.touchHandler.sendKeyCodeEventMsg(
        PROTOCOL_CONFIG.KEYEVENT_KEYCODE_TYPE.ACTION_DOWN,
        PROTOCOL_CONFIG.PC_INUPT_MAP[event.keyCode],
      );
      this.touchHandler.sendKeyCodeEventMsg(
        PROTOCOL_CONFIG.KEYEVENT_KEYCODE_TYPE.ACTION_UP,
        PROTOCOL_CONFIG.PC_INUPT_MAP[event.keyCode],
      );
    }
  }

  handleInputMsg(input, msgType, textType) {
    const PACKAGE_HEADER_LENGTH = 8;
    const INPUT_HEADER_LENGTH = 3;
    const msgData = this.util.encodeUTF8(input);
    const cmdBuf = new Uint8Array(
      PACKAGE_HEADER_LENGTH + INPUT_HEADER_LENGTH + msgData.length,
    );
    cmdBuf[0] = 90;
    cmdBuf[1] = 90;
    cmdBuf[2] = 180 + PROTOCOL_CONFIG.MSG_TYPE[msgType];
    cmdBuf[3] = PROTOCOL_CONFIG.MSG_TYPE[msgType];
    cmdBuf[4] = (INPUT_HEADER_LENGTH + msgData.length) >> 24;
    cmdBuf[5] = (INPUT_HEADER_LENGTH + msgData.length) >> 16;
    cmdBuf[6] = (INPUT_HEADER_LENGTH + msgData.length) >> 8;
    cmdBuf[7] = INPUT_HEADER_LENGTH + msgData.length;
    cmdBuf[8] = textType;
    cmdBuf[9] = msgData.length >> 8;
    cmdBuf[10] = msgData.length;

    cmdBuf.set(msgData, PACKAGE_HEADER_LENGTH + INPUT_HEADER_LENGTH);
    this.msgHandler(cmdBuf.buffer);
    this.input.value = '';
  }

  destroy() {
    this.util.unbind(this.input, 'input');
    this.util.unbind(this.input, 'keyup');
    this.util.unbind(this.input, 'keydown');
    this.util.unbind(this.input, 'compositionstart');
    this.util.unbind(this.input, 'compositionend');
    this.inputContainer.remove();
    this.inputContainer = null;
  }

  sendClipboardData(clipboardData) {
    if (!this.isMobile) {
      return;
    }
    let sendMsgCode =
      PROTOCOL_CONFIG.KEYBOARD_INPUT_MSG_TYPE.IME_PASTE_FROM_SDK;
    this.handleInputMsg(clipboardData, 'KEYBOARD_INPUT', sendMsgCode);
  }
}
